#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <unistd.h>


pthread_mutex_t mutex;	//定义互斥锁

/***********************************************
 * 函数名称： void *client_fun(void *arg)
 * 函数功能： 线程函数，处理客户信息
 * 函数参数： 已连接套接字
 * 函数返回： 无
 * *********************************************/
void *client_fun(void *arg)
{
	int recv_len = 0;
    int connfd = *(int *)arg;		//传过来的已连接的套接字
	char recv_buff[1024] = "";

	// 解锁，pthread_mutex_lock()唤醒，不阻塞
	pthread_mutex_unlock(&mutex);
	
	while((recv_len = recv(connfd, recv_buff, sizeof(recv_buff), 0)) > 0)
	{
		printf("recv_buf : %s\n", recv_buff);
		send(connfd, recv_buff, recv_len, 0);
	}

	printf("client closed!");

	close(connfd);

	return NULL;
}

int tcp_server_pthread()
{
    int err_log = 0;
    int sockfd = 0;
	int connfd = 0;
    int port = 8080;    //监听端口

	pthread_t thread_id = 0;

    struct sockaddr_in my_addr;

	pthread_mutex_init(&mutex, NULL); // 初始化互斥锁，互斥锁默认是打开的
	
    //创建TCP套接字(三次握手)
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket error");
        exit(-1);
    }

    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(port);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    printf("Binding server to port %d\n", port);

    //绑定
    err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
    if (err_log != 0)
    {
        perror("Bind error");
        close(sockfd);
        exit(-1);
    }

    //监听，套接字被动
    err_log = listen(sockfd, 10);
    if (err_log != 0)
    {
        perror("Listen error");
        close(sockfd);
        exit(-1);
    }

    printf("Waiting client...\n");

    while(1)
    {
    	char cli_ip[INET_ADDRSTRLEN] = ""; 		//用户保存客户端IP地址
    	struct sockaddr_in client_addr;		   	//用于保存客户端地址
    	socklen_t cliaddr_len = sizeof(client_addr);	//必须初始化


		// 上锁，在没有解锁之前，pthread_mutex_lock()会阻塞
		pthread_mutex_lock(&mutex);
		
        connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);
		if (connfd < 0)
		{
			perror("accept this time");
			continue;
		}

		inet_ntop(AF_INET, &client_addr, cli_ip, INET_ADDRSTRLEN);

		if (connfd > 0)
		{
			pthread_create(&thread_id, NULL, (void *)client_fun, (void *)&connfd);
			pthread_detach(thread_id);	//线程分离，结束时自动回收资源
		}

    }

	close(sockfd);

	return 0;
    
}